﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace helloworld2.MODEL
{
    class PathFinder
    {
        public double batAmount { get; set; } //km antal
        Vertex cityStart;
        Vertex cityEnd;
        Vertex originalCityEnd;
        Vertex pV; // previous vertex
        List<List<Edge>> roadToGoal = new List<List<Edge>>();
        double cost = 0;
        List<KeyValuePair<double, int>> roadCost = new List<KeyValuePair<double, int>>();
        List<Edge> visited = new List<Edge>();
        Vertex previous;
        Vertex current;
        VertexContainer vc = VertexContainer.Instance;
        EdgeContainer ec = EdgeContainer.Instance;
        //List<List<Vertex>> pathContainer = new List<List<Vertex>>();
        List<Vertex> shortestPath = new List<Vertex>();
        List<Vertex> visitedVertices = new List<Vertex>();
        List<Vertex> path = new List<Vertex>();
        Image img = Image.Instance;

        public PathFinder(Vertex cityStart, Vertex cityEnd)
        {
            Console.WriteLine("Pathfinding starter her");

            this.batAmount = 90;
            this.cityStart = cityStart;
            this.cityEnd = cityEnd;
            this.originalCityEnd = cityEnd;


            //Do some DJ Ikstra
            foreach (Vertex vt in vc.getVertices())
            {
                vt.initializeVertex();
            }
            cityStart.distance = 0;
            findPath(cityStart);
            buildPath();
            img.drawPath(path);


        }

        private void findPath(Vertex v) // v = source
        {
            v.visited = true;
            visitedVertices.Add(v);
            bool end = false;

            if (v.id == this.cityEnd.id)
            {
                end = true;
            }

            Vertex shortVer = new Vertex();
            double shortNum = double.PositiveInfinity;

            foreach (Edge e in v.getConnection())
            {
                foreach (Vertex n in e.getConnection())
                {
                    if (n != v && !n.visited)
                    {                      
                        if (v.distance + e.length < n.distance) 
                        {
                            n.distance = v.distance + e.length;
                            n.pD = v;
                        }
                        relax(n);
                    }                   
                }                
            }

            foreach (Vertex vv in vc.getVertices())
            {
                if (vv.visited == false && vv.distance < shortNum)
                {
                    shortNum = vv.distance;
                    shortVer = vv;
                }
            }

            batAmount = batAmount - (shortVer.distance - v.distance);

            if (batAmount < 0)
            {
                Console.WriteLine("BAT DIDN'T MAKE IT");
                //search for nearby stations, set as intermediate vertex
                //Use Dijkstras from source to intermediate, then from intermediate to destination.
                //if from I to dest, also isn't possible - 

                //List<Vertex> nearbyStations = img.getNearbyStations(this.cityStart.getCenter());
                //findPathToIntermediate(nearbyStations);
            }

            if (!end)
            {
                findPath(shortVer);
            }
            else
            {
                Console.WriteLine("Path ended!");
            }        
        }


        private void relax(Vertex v)
        {
            foreach (Edge e in v.getConnection())
            {
                foreach (Vertex n in e.getConnection())
                {
                    if (n.visited)  
                    {
                        if (v.distance > n.distance + e.length)
                        {
                            v.distance = n.distance + e.length;
                            v.pD = n;
                        }
                    }
                }
            }
        }

        private void buildPath()
        {
            Vertex next = this.cityEnd;               
            path.Add(next);
            bool end = false;
            while (!end)
            {
                path.Add(next.pD);
                next = next.pD;
                if (next == this.cityStart)
                {
                    end = true;
                }
            }
        
            foreach (Vertex ep in path)
            {
                Console.WriteLine("PATHCONTAINER ep: " + ep.id + "  " + ep.distance);
            }

            foreach (Vertex ko in vc.getVertices())
            {
                Console.WriteLine("VC " + ko.id + "  " + ko.distance);
            }


        }

        private void findPathToIntermediate(List<Vertex> iList)
        {
            List<Vertex> path = new List<Vertex>();
            foreach (Vertex v in iList)
            {
                this.cityEnd = v;
                v.initializeVertex();
                findPath(this.cityStart);
                buildPath();
                img.drawPath(path);
            }
        }

    }
}
